import pdb, sys, code
sys.path.append('.')
import os, unittest, filecmp, swmmio, ConfigParser, swmmr
from datetime import datetime

class SWMMRTestCase(unittest.TestCase):
    def setUp(self):
        self.testcases_dir = 'testfiles'
        self.logpath = os.path.join(self.testcases_dir, 'testsuite.log')
        cfg_path = os.path.join(self.testcases_dir, 'testsuite.ini')

        parser = ConfigParser.SafeConfigParser()
        parser.read(cfg_path)
        self.server = eval(parser.get('main', 'server'))
        self.admin = eval(parser.get('main', 'login'))
        self.password = eval(parser.get('main', 'password'))
        setup_path = eval(parser.get('main', 'setup_path'))

        swmmr.build(server = self.server, admin_login = self.admin, admin_password = self.password, setup_path = setup_path)
        self.directory = None
        self.model = None

    def tearDown(self):
        pass

    def test_expectations(self):
        swmmrh = swmmr.handle(server=self.server, login = 'modelking', password = 'sunnyday')
        if self.directory is not None:
            expectations_dir = os.path.join(self.directory, 'expectations')
            tables = os.listdir(expectations_dir)
            all_match = True
            with open(self.logpath, 'a') as f:
                f.write('\n' + str(datetime.now()) + '-' + self.__class__.__name__ + '\n')
                for table in tables:
                    expectation_path = os.path.join(expectations_dir, table)
                    differences = swmmrh.diffCSV(table, csv_path = expectation_path)
                    if len(differences) > 0:
                        if all_match:
                            f.write(table + str(differences) + '\n')
                        else:
                            f.write(table + str(differences) + '\n')
                        all_match = False
            return all_match

    def test_export(self, modelname):
        swmmrh = swmmr.handle(server = self.server, login = 'modelking', password = 'sunnyday')
        outpath = os.path.join(self.directory, 'expectations', modelname + '_exported.inp')
        swmmrh.exportModel(modelname, outpath, preamble=False)

        expected_path = os.path.join(self.directory, 'expectations', modelname + '_expected.inp')
        return filecmp.cmp(expected_path, outpath)

class TestCase01(SWMMRTestCase):
    def runTest(self):
        self.directory = os.path.join(self.testcases_dir, '01')
        model = 'UseCase01'

        inp_files = ['system01.inp', 'system02.inp', 'system03.inp', 'system04.inp']
        inp_paths = [os.path.join(self.directory, inp_file) for inp_file in inp_files]

        version_names = ['version1', 'version2', 'version3', 'version4']
        descriptions = ['desc1', 'desc2', 'desc3', 'desc4']
        tags = ['tag1', 'tag1,tag2', 'tag1,tag3', 'tag2,tag4']

        for i, inp_path in enumerate(inp_paths):
            swmmrh = swmmr.handle(server=self.server, login = 'modeler1', password = 'sunnyday')
            swmmrh.importINP(model = model, 
                              inp_path = inp_path, 
                              swmmbuild = '5.0.022',
                              version = version_names[i],
                              desc = descriptions[i],
                              tags_csv = tags[i]
                              )
            swmmrh.commit()
            del swmmrh

        self.assertTrue(self.test_expectations())


class TestCase02(SWMMRTestCase):
    def runTest(self):
        model = 'UseCase02'
        self.directory = os.path.join(self.testcases_dir, '02')

        inp_files = ['system01.inp', 'system02.inp']
        inp_paths = [os.path.join(self.directory, inp_file) for inp_file in inp_files]

        for i, inp_path in enumerate(inp_paths):
            swmmrh = swmmr.handle(server=self.server, login = 'modeler1', password = 'sunnyday')
            swmmrh.importINP(model = model, 
                                        inp_path = inp_path,
                                        swmmbuild = '5.0.022',
                                        version = 'version1',
                                        desc = 'description',
                                        tags_csv = 'tag1,tag2')
            if i == 0:
                swmmrh.commit()
            del swmmrh

        self.assertTrue(self.test_expectations())

class TestCase03(SWMMRTestCase):
    def runTest(self):
        self.directory = os.path.join(self.testcases_dir, '03')

        inp_files = ['system01.inp', 'system02.inp', 'system03.inp', 'system04.inp']
        inp_paths = [os.path.join(self.directory, inp_file) for inp_file in inp_files]
        model1 = 'UseCase03 Version1'
        model2 = 'UseCase03 Version2'
        models = [model1, model2, model2, model2]
        version_names = ['version1', 'version1', 'version2', 'version3']

        tags_csv = 'tag1,tag2'
        for i, inp_path in enumerate(inp_paths):
            swmmrh = swmmr.handle(server = self.server, login = 'modeler1', password = 'sunnyday')
            swmmrh.importINP(model = models[i], 
                            inp_path = inp_path, 
                            swmmbuild = '5.0.022',
                            version = version_names[i],
                            desc = 'description',
                            tags_csv = tags_csv
                            )

            if i == 2: # on second import for second model, cascade shared elements to first model
                swmmrh.prepCascade(models[i], tags_csv=tags_csv)
                swmmrh.CME_SetSubsetState(1)
                swmmrh.CME_Commit(models[i])
            swmmrh.commit()
            del swmmrh

        self.assertTrue(self.test_expectations())

class TestCase04(SWMMRTestCase):
    def runTest(self):
        model = 'UseCase04'
        self.directory = os.path.join(self.testcases_dir, '04')

        inp_files = ['system05.inp', 'system06.inp', 'system07.inp', 'system08.inp']
        inp_paths = [os.path.join(self.directory, inp_file) for inp_file in inp_files]
        version_names = ['version1', 'version2', 'version3', 'version4']

        for i, inp_path in enumerate(inp_paths):
            swmmrh = swmmr.handle(server=self.server, login = 'modeler1', password = 'sunnyday')
            swmmrh.importINP(model = model, 
                            inp_path = inp_path, 
                            swmmbuild = '5.0.022',
                            version = version_names[i],
                            desc = 'description',
                            tags_csv = 'tag1,tag2'
                            )
            swmmrh.commit()
            del swmmrh

        self.assertTrue(self.test_expectations())

class TestCase05(SWMMRTestCase):
    def runTest(self):
        self.directory = os.path.join(self.testcases_dir, '05')

        inp_file = 'system09.inp'
        inp_path = os.path.join(self.directory, inp_file)
        model = 'UseCase05'

        inp = swmmio.INP(inp_path)
        sections = inp.getSections()
        supported_sections = inp.getSupportedSections()
        self.assertTrue(set(sections) == set(supported_sections))

        swmmrh = swmmr.handle(server = self.server, login = 'modeler1', password = 'sunnyday')
        swmmrh.importINP(model = model, 
                        inp_path = inp_path, 
                        swmmbuild = '5.0.022',
                        version = 'version1',
                        desc = 'description',
                        tags_csv = 'tag1,tag2'
                        )
        swmmrh.commit()
        del swmmrh
        self.assertTrue(self.test_export(model))

class TestCase06(SWMMRTestCase):
    def runTest(self):
        self.directory = os.path.join(self.testcases_dir, '06')

        inp_files = ['system01.inp', 'system11.inp', 'system12.inp']
        inp_paths = [os.path.join(self.directory, inp_file) for inp_file in inp_files]

        login = 'modeler1'
        model1 = 'UseCase06a'
        inp_path = inp_paths[0]
        swmmrh = swmmr.handle(server = self.server, login = login, password = 'sunnyday')
        swmmrh.importINP(model = model1, 
                        inp_path = inp_path, 
                        swmmbuild = '5.0.022',
                        version = 'version1',
                        desc = 'description',
                        tags_csv = 'tag1,tag2'
                        )
        swmmrh.commit()
        del swmmrh

        login = 'modeler2'
        model2 = 'UseCase06b'
        inp_path = inp_paths[1]
        swmmrh1 = swmmr.handle(server = self.server, login = login, password = 'sunnyday')
        swmmrh1.importINP(model = model2, 
                                    inp_path = inp_path, 
                                    swmmbuild = '5.0.022',
                                    version = 'version1',
                                    desc = 'description',
                                    tags_csv = 'tag1,tag2'
                                    )
        swmmrh1.prepCascade(model2, tags_csv='tag1')
        swmmrh1.CME_SetSubsetState(1)
        swmmrh1.CME_Commit(model2)

        login = 'modeler1'
        inp_path = inp_paths[2]
        swmmrh2 = swmmr.handle(server = self.server, login = login, password = 'sunnyday')
        swmmrh2.importINP(model = model1, 
                                    inp_path = inp_path, 
                                    swmmbuild = '5.0.022',
                                    version = 'version2',
                                    desc = 'description',
                                    tags_csv = 'tag1,tag2'
                                    )
        swmmrh2.commit()
        del swmmrh2
        swmmrh1.commit()
        del swmmrh1
        self.assertTrue(self.test_export(model1) and self.test_export(model2))

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(TestCase01())
    suite.addTest(TestCase02())
    suite.addTest(TestCase03())
    suite.addTest(TestCase04())
    suite.addTest(TestCase05())
    suite.addTest(TestCase06())
    #suite = unittest.TestLoader().loadTestsFromTestCase(test_HHMODEL)
    unittest.TextTestRunner(verbosity=2).run(suite)
